package com.googlecode.continuity.core.server.mvc.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.acegisecurity.AuthenticationException;
import org.acegisecurity.BadCredentialsException;
import org.acegisecurity.ui.webapp.AuthenticationProcessingFilter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import com.googlecode.continuity.core.server.mvc.ContinuityModel;
import com.googlecode.continuity.core.server.security.authentication.ContinuityAuthenticationProcessingFilter;

/**
 * The LoginController serves a login page, working in close interaction with the
 * {@link com.googlecode.continuity.core.server.security.authentication.ContinuityAuthenticationProcessingFilter}. It
 * serves notifications of errors that occur during compile time and differs between a "goto login" (a login with an
 * explicit target page) and a "normal login" (where the user requested a page requiring authentication and Acegi calls
 * the login page before continuing to the original page).
 */
public class LoginController implements Controller {
  /**
   * Logger for this class and subclasses
   */
  protected final Log logger = LogFactory.getLog(getClass());

  /**
   * Handles a request for the login page, looking up possible errors in the session.
   *
   * @param request http request
   * @param response http response
   * @return model and view for login
   * @throws ServletException
   * @throws IOException
   */
  public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    ContinuityModel model = new ContinuityModel();

    // add goto information
    model.put("gotoLogin",
        "1".equals(request.getParameter(ContinuityAuthenticationProcessingFilter.CONTINUITY_GOTO_URL_PARAM)));

    // add error information if available
    boolean error = request.getParameter("login_error") != null && request.getParameter("login_error").equals("1");
    model.put("error", error);
    if (error) {
      // todo: i18n error messages
      String errorMessage;
      AuthenticationException exception = (AuthenticationException) request.getSession()
          .getAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY);
      if (exception instanceof BadCredentialsException) {
        errorMessage = "Your username and password did not match. Please try again.";
      } else {
        errorMessage = "An error occured during login, please try again.";
        logger.warn("Unhandled authentication exception occured during login.", exception);
      }
      model.put("errorMessage", errorMessage);

      model.put("lastUsername",
          request.getSession().getAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_USERNAME_KEY));
    }

    logger.debug("Returning login.");

    return new ModelAndView("login", model);
  }
}
